using dotnet_ef_admin.Src.Common.Const;
using dotnet_ef_admin.Src.Models;

using Microsoft.EntityFrameworkCore;

namespace dotnet_ef_admin.Src.Services;

/// <summary>
///     字典服务类，用于处理字典相关的操作，如获取、创建、更新和删除字典信息。
/// </summary>
public class DictService : IDictService {
    private readonly DbCtx _context;

    public DictService(DbCtx context) {
        _context = context;
    }

    /// <summary>
    ///     获取所有字典的列表。
    /// </summary>
    /// <param name="query">包含分页和关键词的查询条件。</param>
    /// <returns>返回一个包含所有字典的结果，包括字典列表和总计数。</returns>
    public async Task<GetAllDictsResult> FindAllAsync(FindAllDictsDto query) {
        // 根据关键词过滤字典
        var queryWhere = _context.DictTypes
            .Where(d => string.IsNullOrEmpty(query.Keywords) || d.Name.Contains(query.Keywords));

        // 执行查询，分页并排序
        var dictTypeList = await queryWhere
            .OrderByDescending(d => d.Id)
            .Skip(((query.PageNum ?? BasePageQuery.PageNum) - 1) * (query.PageSize ?? BasePageQuery.PageSize))
            .Take(query.PageSize ?? BasePageQuery.PageSize)
            .Select(d => new DictEntryResult {
                Id = d.Id,
                Name = d.Name,
                Status = d.Status ?? 0,
                Code = d.Code,
                DictItems = d.Dicts != null ? d.Dicts.Select(di => new DictItemResult {
                    Id = di.Id, Name = di.Name ?? "", Value = di.Value ?? "", Sort = di.Sort ?? 0
                }).ToList() : new List<DictItemResult>()
            })
            .ToListAsync();

        // 获取符合条件的字典总数
        var count = await queryWhere.CountAsync();

        // 返回字典列表和总数
        return new GetAllDictsResult { List = dictTypeList, Total = count };
    }

    /// <summary>
    ///     根据字典ID获取字典信息。
    /// </summary>
    /// <param name="id">字典的唯一标识符。</param>
    /// <returns>返回与ID匹配的字典，如果没有找到，则返回null。</returns>
    public async Task<DictEntryResult?> FindFormAsync(int id) {
        // 查找指定ID的字典项
        var existingDict = await _context.DictTypes
        .Include(dt => dt.Dicts)  // 显式加载Dicts集合
        .FirstOrDefaultAsync(dt => dt.Id == id)
        ?? throw new Exception($"找不到ID为{id}的字典。");

        // 返回找到的字典信息
        return new DictEntryResult {
            Id = existingDict.Id,
            Status = existingDict.Status ?? 0,
            Name = existingDict.Name,
            Code = existingDict.Code,
            DictItems = existingDict.Dicts?.Select(di => new DictItemResult {
                Id = di.Id, Name = di.Name ?? "", Value = di.Value ?? "", Sort = di.Sort ?? 0
            }).ToList()
        };
    }

    /// <summary>
    ///     创建字典并保存到数据库。
    /// </summary>
    /// <param name="dict">要创建的字典对象。</param>
    /// <returns>返回创建的字典信息。</returns>
    public async Task<DictEntryResult> CreateAsync(DictEntry dict) {
        // 检查字典名称是否已存在
        var existingDict = _context.DictTypes.FirstOrDefault(d => d.Name == dict.Name);
        if (existingDict != null) throw new Exception($"字典“{dict.Name}”已存在。");

        // 创建新的字典实例
        var newDict = new DictType {
            Name = dict.Name,
            Code = dict.Code,
            Status = dict.Status,
            Dicts = dict.DictItems?.Select(di => new Dict {
                Name = di.Name,
                Value = di.Value,
                Sort = di.Sort,
                Status = di.Status,
                CreateTime = DateTime.Now
            }).ToList() ?? []
        };

        // 将新字典添加到上下文并保存
        await _context.DictTypes.AddAsync(newDict);
        await _context.SaveChangesAsync();

        // 返回新创建的字典信息
        return new DictEntryResult {
            Id = newDict.Id,
            Status = newDict.Status ?? 0,
            Name = newDict.Name,
            Code = newDict.Code,
            DictItems = newDict.Dicts.Select(d => new DictItemResult {
                Id = d.Id,
                Name = d.Name ?? "",
                Value = d.Value ?? "",
                Sort = d.Sort ?? 0,
                Status = d.Status ?? 0
            }).ToList()
        };
    }

    /// <summary>
    ///     更新数据库中的现有字典。
    /// </summary>
    /// <param name="id">要更新的字典的唯一标识符。</param>
    /// <param name="dict">包含更新信息的字典对象。</param>
    /// <returns>返回更新后的字典信息。</returns>
    public async Task<DictEntryResult> UpdateAsync(int id, DictEntryResult dict) {
        // 查找现有字典及其相关字典项
        var existingDict = await _context.DictTypes
            .Include(dt => dt.Dicts) // 确保加载相关字典项
            .FirstOrDefaultAsync(d => d.Id == id)
            ?? throw new Exception($"找不到ID为{id}的字典。");

        // 更新字典信息
        _context.Entry(existingDict).CurrentValues.SetValues(dict);

        if (dict.DictItems != null) {
            // 获取现有的 DictItems
            var existingItems = existingDict.Dicts == null ? new List<Dict>() : [.. existingDict.Dicts];

            // 更新现有字典项或添加新的字典项
            foreach (var item in dict.DictItems) {
                if (item.Id > 0) {
                    var existingItem = existingItems.FirstOrDefault(di => di.Id == item.Id);
                    if (existingItem != null) {
                        _context.Entry(existingItem).CurrentValues.SetValues(item);
                    }
                } else {
                    _context.Dicts.Add(new Dict {
                        Name = item.Name,
                        Value = item.Value,
                        Sort = item.Sort,
                        Status = item.Status,
                        DictTypeId = existingDict.Id
                    });
                }
            }

            // 删除不存在于请求中的字典项
            var itemsToDelete = existingItems
                .Where(di => !dict.DictItems.Any(item => item.Id == di.Id))
                .ToList();

            _context.Dicts.RemoveRange(itemsToDelete);
        }

        // 保存更改
        await _context.SaveChangesAsync();

        // 返回更新后的字典信息
        return new DictEntryResult {
            Id = existingDict.Id,
            Status = existingDict.Status ?? 0,
            Name = existingDict.Name,
            Code = existingDict.Code
        };
    }


    /// <summary>
    ///     根据提供的ID数组批量删除字典。
    /// </summary>
    /// <param name="ids">要删除的字典ID数组。</param>
    /// <returns>返回成功删除的字典数量。</returns>
    public async Task<int> DeleteManyAsync(int[] ids) {
        // 查询要删除的字典
        var deleteIds = await _context.DictTypes.Where(r => ids.Contains(r.Id)).ToListAsync();

        // 从上下文移除找到的字典
        _context.DictTypes.RemoveRange(deleteIds);

        // 保存更改并返回删除的数量
        return await _context.SaveChangesAsync();
    }
}